﻿namespace AzManAPI
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using Microsoft.Interop.Security.AzRoles;
    using System.Runtime.InteropServices;
    using System.ComponentModel;   

    public class PolicyStore : INotifyPropertyChanged
    {
        private IAzAuthorizationStore3 authorizationStore;
        private List<Application> applications;
        private string policyUrl;
        private bool isConnected, isValid;

        public ReadOnlyCollection<Application> Applications
        {
            get 
            {
                if (applications == null)
                {
                    applications = GetApplications();
                }

                return new ReadOnlyCollection<Application>(applications); 
            }
        }

        public string PolicyUrl
        {
            get { return policyUrl; }
            set
            {
                if (!IsConnected && policyUrl != value)
                {
                    policyUrl = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("PolicyUrl"));
                    IsValid = GetIsValid();

                    if (IsValid)
                    {
                        Connect();
                    }
                }
            }
        }

        public List<Application> GetApplications()
        {
            if (!IsConnected)
                return null;

            List<Application> ret = new List<Application>();

            IEnumerable apps = (IEnumerable)authorizationStore.Applications;

            IEnumerator enumerator = apps.GetEnumerator();
            
            while (enumerator.MoveNext())
            {
                ret.Add(new Application((IAzApplication3)enumerator.Current));
            }

            return ret;
        }

        public Application GetApplication(string name)
        {
            throw new NotImplementedException();
        }

        public bool IsConnected
        {
            get { return isConnected; }
            set
            {
                if (isConnected != value)
                {
                    isConnected = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("IsConnected"));
                    OnPropertyChanged(new PropertyChangedEventArgs("Applications"));
                }
            }
        }

        public bool IsValid
        {
            get { return isValid; }
            set
            {
                if (isValid != value)
                {
                    isValid = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("IsValid"));
                }
            }
        }

        private bool GetIsValid()
        {
            bool isValid = false;
            AzAuthorizationStoreClass validityTestStoreObject = new AzAuthorizationStoreClass();

            try
            {
                validityTestStoreObject.Initialize(0, PolicyUrl);
                isValid = true;
            }
            catch { /* not valid */ }
            finally
            {
                Marshal.ReleaseComObject(validityTestStoreObject);
                validityTestStoreObject = null;
            }

            return isValid;
        }

        public void Connect()
        {
            authorizationStore = new AzAuthorizationStoreClass();
            authorizationStore.Initialize(0, PolicyUrl);
            authorizationStore.UpdateCache();
            IsConnected = true;
        }

        public void Disconnect()
        {
            Marshal.ReleaseComObject(authorizationStore);
            authorizationStore = null;
            IsConnected = false;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, e);
            }
        }

        #endregion
    }
}